#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pcap.h>

#define MAXBYTES2CAPTURE 2048

void ProcessPacket(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet)
{
    int i = 0, *counter = (int *)arg;

    printf("Packet Count : %d\n", ++(*counter));
    printf("Received Packet Size: %d\n", pkthdr->len);
    printf("Payload:\n");
    for (i = 0; i < pkthdr->len; i++)
    {
        printf("%02x  ", (unsigned int)packet[i]);

        if ((i % 16 == 15 && i != 0) || (i == pkthdr->len - 1))
        {
            printf("\n");
        }
    }
    printf("\n\n************************************************\n");
    return;
}

int main(int argc, char *argv[])
{
    int i = 0, count = 0,ret ;
    pcap_t *descr = NULL;
    char errbuf[PCAP_ERRBUF_SIZE], *device = NULL;
    bpf_u_int32 netaddr = 0, mask = 0;
    struct bpf_program filter;

    memset(errbuf, 0, sizeof(errbuf)); // 数组清空 

    if (argc != 2)
    {
        // 查新网卡 
        device = pcap_lookupdev(errbuf); // 系统自动搜索网卡 
    }
    else
    {
        device = argv[1];  // ./20-pcap ens33  , 手动指定 
    }
    printf("Try to open device %s\n", device);

    // 打开网卡设备 
    if ((descr = pcap_open_live(device, MAXBYTES2CAPTURE, 1, 0, errbuf)) < 0)
    {
        printf("error : %s\n", errbuf);
        exit(-1);
    }

    // 查询网络连接信息
    ret = pcap_lookupnet(device, &netaddr, &mask, errbuf);
    if(ret < 0)
    {
        printf("error : %s\n", errbuf);
        exit(-1);
    }
    // 生成过滤器 
  /*
    //抓主机网卡
    if (pcap_compile(descr, &filter, "ether host 00:0c:29:3c:74:fd",0, mask) < 0)
    {
        printf("pcap_compile error\n");
        exit(-1);
    }
  */
    //抓arp协议
    if (pcap_compile(descr, &filter, "arp and ether host 00:0c:29:3c:74:fd",0, mask) < 0)
    {
        printf("pcap_compile error\n");
        exit(-1);
    }
    // 安装过滤器 
    pcap_setfilter(descr, &filter);

    // 抓取数据包 
    pcap_loop(descr, 2, ProcessPacket, (u_char *)&count);

    return 0;
}
